package com.neonbacon.snake;

import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.util.Log;

public class EntitySnake {
	public static final int DIR_LEFT = 0;
	public static final int DIR_RIGHT = 1;
	public static final int DIR_UP = 2;
	public static final int DIR_DOWN = 3;

	int dir = EntitySnake.DIR_UP;
	CopyOnWriteArrayList<SnakeBody> parts = new CopyOnWriteArrayList<SnakeBody>();
	SnakeBody head;
	CopyOnWriteArrayList<TurnPos> turns = new CopyOnWriteArrayList<TurnPos>();

	int arraypos = 0;
	Level l;

	public EntitySnake(int x, int y, Context c, Level l) {
		this.l = l;
		Matrix matrix = new Matrix();
		matrix.postRotate(-90);
		InGame.head = Bitmap.createBitmap(InGame.head, 0, 0,
				InGame.head.getWidth(), InGame.head.getHeight(), matrix, true);
		head = new SnakeBody(x, y, this, InGame.head);
		parts.add(new SnakeBody(x, y + 1, this, 0));
		parts.add(new SnakeBody(x, y + 2, this, 1));
	}

	public void render(Canvas c) {
		head.render(c);
		for (SnakeBody b : parts) {
			b.render(c);
		}
	}

	public void addPart() {
		if (getLastPart().dir == EntitySnake.DIR_UP) {
			SnakeBody b = new SnakeBody(getLastPart().x, getLastPart().y + 1,
					this, 0);
			b.dir = EntitySnake.DIR_UP;
			parts.add(b);
		}
		if (getLastPart().dir == EntitySnake.DIR_DOWN) {
			SnakeBody b = new SnakeBody(getLastPart().x , getLastPart().y - 1,
					this, 0);
			b.dir = EntitySnake.DIR_DOWN;
			parts.add(b);
		}
		if (getLastPart().dir == EntitySnake.DIR_LEFT) {
			SnakeBody b = new SnakeBody(getLastPart().x + 1, getLastPart().y,
					this, 0);
			b.dir = EntitySnake.DIR_LEFT;
			parts.add(b);
		}
		if (getLastPart().dir == EntitySnake.DIR_RIGHT) {
			SnakeBody b = new SnakeBody(getLastPart().x - 1, getLastPart().y,
					this, 0);
			b.dir = EntitySnake.DIR_RIGHT;
			parts.add(b);
		}
	}

	public void update() {
		head.update(0);
		for (int i = 0; i != parts.size(); i++) {
			parts.get(i).update(i);
			Log.d("JACK","UPDATED " + parts.size());
			if (i == parts.size() -1) {
				parts.get(i).onLoopEnd();
			}
		}

	}

	public void move(int dir) {
		this.dir = dir;
	}

	class SnakeBody {
		int x;
		int y;
		EntitySnake parent;
		Bitmap body;
		int dir = EntitySnake.DIR_UP;
		int arraypos;
        int lastx;
        int lasty;
		public SnakeBody(int x, int y, EntitySnake parent, int arraypos) {
			this.x = x;
			this.y = y;
			this.parent = parent;
			this.arraypos = arraypos;
		}

		public SnakeBody(int x, int y, EntitySnake parent, Bitmap body) {
			this.x = x;
			this.y = y;
			this.parent = parent;
			this.body = body;
		}

		public void render(Canvas c) {
			if (body == null)
				c.drawBitmap(InGame.body, x * InGame.body.getWidth(), y
						* InGame.body.getHeight(), null);
			else
				c.drawBitmap(body, x * InGame.body.getWidth(),
						y * InGame.body.getHeight(), null);

		}

		public void update(int pos) {
			lastx = x;
			lasty = y;
			if (body != null) {
				int lvlpos = (x + y * l.lwidth);
				if (lvlpos == l.foodpos) {
					l.map[l.foodpos] = 1;
					l.onFoodEat();
					l.s.addPart();
				}

			}
			for(TurnPos turnpos : turns){
				if(turnpos.x == x && turnpos.y == y){
					dir = turnpos.dir;
				}
			}
			if (dir == EntitySnake.DIR_UP) {
				y--;
			}
			if (dir == EntitySnake.DIR_DOWN) {
				y++;
			}
			if (dir == EntitySnake.DIR_LEFT) {
				x--;
			}
			if (dir == EntitySnake.DIR_RIGHT) {
				x++;
			}
		}

		public void onLoopEnd() {
			Log.d("JACK","Loop end");
			for(TurnPos turnpos : turns){
				if(turnpos.x == lastx && turnpos.y == lasty){
					turns.remove(turnpos);
					Log.d("JACK","REMOVED");
				}
			}
		}
	}

	public void setDir(int dir) {
		turns.add(new TurnPos(head.x, head.y, dir));
	}
	private SnakeBody getLastPart(){
		for (int i = 0; i != parts.size(); i++) {
			if (i == parts.size() - 1) {
				return parts.get(i);
			}
		}
		return null;
	}
}
